home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / blend.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-09  |  42.3 KB  |  1,641 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "asupsample.h"
  29. #include "blend.h"
  30. #include "cursorutil.h"
  31. #include "draw_core.h"
  32. #include "drawable.h"
  33. #include "errors.h"
  34. #include "fuzzy_select.h"
  35. #include "gdisplay.h"
  36. #include "gimage_mask.h"
  37. #include "gimpdnd.h"
  38. #include "gimpui.h"
  39. #include "gradient.h"
  40. #include "paint_options.h"
  41. #include "selection.h"
  42. #include "tools.h"
  43. #include "undo.h"
  44.  
  45. #include "tile.h"
  46.  
  47. #include "libgimp/gimpcolorspace.h"
  48. #include "libgimp/gimpmath.h"
  49.  
  50. #include "libgimp/gimpintl.h"
  51.  
  52.  
  53. /*  target size  */
  54. #define  TARGET_HEIGHT    15
  55. #define  TARGET_WIDTH     15
  56.  
  57. #define  STATUSBAR_SIZE  128
  58.  
  59. /*  the blend structures  */
  60.  
  61. typedef gdouble (* RepeatFunc) (gdouble);
  62.  
  63. typedef struct _BlendTool BlendTool;
  64.  
  65. struct _BlendTool
  66. {
  67.   DrawCore *core;        /*  Core select object   */
  68.  
  69.   gint      startx;      /*  starting x coord     */
  70.   gint      starty;      /*  starting y coord     */
  71.  
  72.   gint      endx;        /*  ending x coord       */
  73.   gint      endy;        /*  ending y coord       */
  74.   guint     context_id;  /*  for the statusbar    */
  75. };
  76.  
  77. typedef struct _BlendOptions BlendOptions;
  78.  
  79. struct _BlendOptions
  80. {
  81.   PaintOptions  paint_options;
  82.  
  83.   gdouble       offset;
  84.   gdouble       offset_d;
  85.   GtkObject    *offset_w;
  86.  
  87.   BlendMode     blend_mode;
  88.   BlendMode     blend_mode_d;
  89.   GtkWidget    *blend_mode_w;
  90.  
  91.   GradientType  gradient_type;
  92.   GradientType  gradient_type_d;
  93.   GtkWidget    *gradient_type_w;
  94.  
  95.   RepeatMode    repeat;
  96.   RepeatMode    repeat_d;
  97.   GtkWidget    *repeat_w;
  98.  
  99.   gint          supersample;
  100.   gint          supersample_d;
  101.   GtkWidget    *supersample_w;
  102.  
  103.   gint          max_depth;
  104.   gint          max_depth_d;
  105.   GtkObject    *max_depth_w;
  106.  
  107.   gdouble       threshold;
  108.   gdouble       threshold_d;
  109.   GtkObject    *threshold_w;
  110. };
  111.  
  112. typedef struct
  113. {
  114.   gdouble      offset;
  115.   gdouble      sx, sy;
  116.   BlendMode    blend_mode;
  117.   GradientType gradient_type;
  118.   color_t      fg, bg;
  119.   gdouble      dist;
  120.   gdouble      vec[2];
  121.   RepeatFunc   repeat_func;
  122. } RenderBlendData;
  123.  
  124. typedef struct
  125. {
  126.   PixelRegion *PR;
  127.   guchar      *row_data;
  128.   gint         bytes;
  129.   gint         width;
  130. } PutPixelData;
  131.  
  132.  
  133. /*  the blend tool options  */
  134. static BlendOptions *blend_options = NULL;
  135.  
  136. /*  variables for the shapeburst algs  */
  137. static PixelRegion distR =
  138. {
  139.   NULL,  /* data */
  140.   NULL,  /* tiles */
  141.   0,     /* rowstride */
  142.   0, 0,  /* w, h */
  143.   0, 0,  /* x, y */
  144.   4,     /* bytes */
  145.   0      /* process count */
  146. };
  147.  
  148. /*  dnd stuff  */
  149. static GtkTargetEntry blend_target_table[] =
  150. {
  151.   GIMP_TARGET_GRADIENT,  
  152.   GIMP_TARGET_TOOL
  153. };
  154. static guint blend_n_targets = (sizeof (blend_target_table) /
  155.                 sizeof (blend_target_table[0]));
  156.  
  157. /*  local function prototypes  */
  158.  
  159. static void   gradient_type_callback    (GtkWidget *, gpointer);
  160.  
  161. static void   blend_button_press        (Tool *, GdkEventButton *, gpointer);
  162. static void   blend_button_release      (Tool *, GdkEventButton *, gpointer);
  163. static void   blend_motion              (Tool *, GdkEventMotion *, gpointer);
  164. static void   blend_cursor_update       (Tool *, GdkEventMotion *, gpointer);
  165. static void   blend_control             (Tool *, ToolAction,       gpointer);
  166.  
  167. static void   blend_options_drop_gradient  (GtkWidget *, gradient_t *, gpointer);
  168. static void   blend_options_drop_tool      (GtkWidget *, ToolType,     gpointer);
  169.  
  170. static double gradient_calc_conical_sym_factor           (double dist, double *axis, double offset,
  171.                               double x, double y);
  172. static double gradient_calc_conical_asym_factor          (double dist, double *axis, double offset,
  173.                               double x, double y);
  174. static double gradient_calc_square_factor                (double dist, double offset,
  175.                               double x, double y);
  176. static double gradient_calc_radial_factor                (double dist, double offset,
  177.                               double x, double y);
  178. static double gradient_calc_linear_factor                (double dist, double *vec, double offset,
  179.                               double x, double y);
  180. static double gradient_calc_bilinear_factor              (double dist, double *vec, double offset,
  181.                               double x, double y);
  182. static double gradient_calc_spiral_factor                (double dist, double *axis, double offset,
  183.                               double x, double y, gint cwise);
  184. static double gradient_calc_shapeburst_angular_factor    (double x, double y);
  185. static double gradient_calc_shapeburst_spherical_factor  (double x, double y);
  186. static double gradient_calc_shapeburst_dimpled_factor    (double x, double y);
  187.  
  188. static double gradient_repeat_none                       (double val);
  189. static double gradient_repeat_sawtooth                   (double val);
  190. static double gradient_repeat_triangular                 (double val);
  191.  
  192. static void   gradient_precalc_shapeburst                (GImage *gimage, GimpDrawable *drawable, 
  193.                               PixelRegion *PR, double dist);
  194.  
  195. static void   gradient_render_pixel                      (double x, double y, 
  196.                               color_t *color, void *render_data);
  197. static void   gradient_put_pixel                         (int x, int y, 
  198.                               color_t color, void *put_pixel_data);
  199.  
  200. static void   gradient_fill_region          (GImage *gimage, GimpDrawable *drawable, PixelRegion *PR,
  201.                          int width, int height,
  202.                          BlendMode blend_mode, GradientType gradient_type,
  203.                          double offset, RepeatMode repeat,
  204.                          int supersample, int max_depth, double threshold,
  205.                          double sx, double sy, double ex, double ey,
  206.                          progress_func_t progress_callback,
  207.                          void *progress_data);
  208.  
  209.  
  210. /*  functions  */
  211.  
  212. static void
  213. gradient_type_callback (GtkWidget *widget,
  214.             gpointer   data)
  215. {
  216.   gimp_menu_item_update (widget, data);
  217.  
  218.   gtk_widget_set_sensitive (blend_options->repeat_w, 
  219.                 (blend_options->gradient_type < 6));
  220. }
  221.  
  222. static void
  223. blend_options_reset (void)
  224. {
  225.   BlendOptions *options = blend_options;
  226.  
  227.   paint_options_reset ((PaintOptions *) options);
  228.  
  229.   options->blend_mode    = options->blend_mode_d;
  230.   options->gradient_type = options->gradient_type_d;
  231.   options->repeat        = options->repeat_d;
  232.  
  233.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w),
  234.                    blend_options->blend_mode_d);
  235.   gtk_option_menu_set_history (GTK_OPTION_MENU (options->gradient_type_w),
  236.                    blend_options->gradient_type_d);
  237.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->repeat_w),
  238.                    blend_options->repeat_d);
  239.  
  240.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->offset_w),
  241.                 blend_options->offset_d);
  242.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (blend_options->supersample_w),
  243.                 blend_options->supersample_d);
  244.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->max_depth_w),
  245.                 blend_options->max_depth_d);
  246.   gtk_adjustment_set_value (GTK_ADJUSTMENT (blend_options->threshold_w),
  247.                 blend_options->threshold_d);
  248. }
  249.  
  250. static BlendOptions *
  251. blend_options_new (void)
  252. {
  253.   BlendOptions *options;
  254.  
  255.   GtkWidget *vbox;
  256.   GtkWidget *table;
  257.   GtkWidget *scale;
  258.   GtkWidget *frame;
  259.  
  260.   /*  the new blend tool options structure  */
  261.   options = g_new (BlendOptions, 1);
  262.   paint_options_init ((PaintOptions *) options,
  263.               BLEND,
  264.               blend_options_reset);
  265.   options->offset       = options->offset_d          = 0.0;
  266.   options->blend_mode      = options->blend_mode_d    = FG_BG_RGB_MODE;
  267.   options->gradient_type = options->gradient_type_d = LINEAR;
  268.   options->repeat        = options->repeat_d        = REPEAT_NONE;
  269.   options->supersample   = options->supersample_d   = FALSE;
  270.   options->max_depth     = options->max_depth_d     = 3;
  271.   options->threshold     = options->threshold_d     = 0.2;
  272.  
  273.   /*  the main vbox  */
  274.   vbox = ((ToolOptions *) options)->main_vbox;
  275.  
  276.   /*  dnd stuff  */
  277.   gtk_drag_dest_set (vbox,
  278.              GTK_DEST_DEFAULT_HIGHLIGHT |
  279.              GTK_DEST_DEFAULT_MOTION |
  280.              GTK_DEST_DEFAULT_DROP,
  281.              blend_target_table, blend_n_targets,
  282.              GDK_ACTION_COPY); 
  283.   gimp_dnd_gradient_dest_set (vbox, blend_options_drop_gradient, NULL);
  284.   gimp_dnd_tool_dest_set (vbox, blend_options_drop_tool, NULL);
  285.  
  286.   /*  the offset scale  */
  287.   table = gtk_table_new (4, 2, FALSE);
  288.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  289.   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
  290.   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
  291.   gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
  292.  
  293.   options->offset_w =
  294.     gtk_adjustment_new (options->offset_d, 0.0, 100.0, 1.0, 1.0, 0.0);
  295.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->offset_w));
  296.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  297.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  298.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  299.                  _("Offset:"), 1.0, 1.0,
  300.                  scale, 1, FALSE);
  301.   gtk_signal_connect (GTK_OBJECT (options->offset_w), "value_changed",
  302.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  303.               &options->offset);
  304.  
  305.   /*  the blend mode menu  */
  306.   options->blend_mode_w = gimp_option_menu_new2
  307.     (FALSE, gimp_menu_item_update,
  308.      &options->blend_mode, (gpointer) options->blend_mode_d,
  309.  
  310.      _("FG to BG (RGB)"),     (gpointer) FG_BG_RGB_MODE, NULL,
  311.      _("FG to BG (HSV)"),     (gpointer) FG_BG_HSV_MODE, NULL,
  312.      _("FG to Transparent"),  (gpointer) FG_TRANS_MODE, NULL,
  313.      _("Custom Gradient"),    (gpointer) CUSTOM_MODE, NULL,
  314.  
  315.      NULL);
  316.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  317.                  _("Blend:"), 1.0, 0.5,
  318.                  options->blend_mode_w, 1, TRUE);
  319.  
  320.   /*  the gradient type menu  */
  321.   options->gradient_type_w = gimp_option_menu_new2
  322.     (FALSE, gradient_type_callback,
  323.      &options->gradient_type, (gpointer) options->gradient_type_d,
  324.  
  325.      _("Linear"),                 (gpointer) LINEAR, NULL,
  326.      _("Bi-Linear"),              (gpointer) BILINEAR, NULL,
  327.      _("Radial"),                 (gpointer) RADIAL, NULL,
  328.      _("Square"),                 (gpointer) SQUARE, NULL,
  329.      _("Conical (symmetric)"),    (gpointer) CONICAL_SYMMETRIC, NULL,
  330.      _("Conical (asymmetric)"),   (gpointer) CONICAL_ASYMMETRIC, NULL,
  331.      _("Shapeburst (angular)"),   (gpointer) SHAPEBURST_ANGULAR, NULL,
  332.      _("Shapeburst (spherical)"), (gpointer) SHAPEBURST_SPHERICAL, NULL,
  333.      _("Shapeburst (dimpled)"),   (gpointer) SHAPEBURST_DIMPLED, NULL,
  334.      _("Spiral (clockwise)"),     (gpointer) SPIRAL_CLOCKWISE, NULL,
  335.      _("Spiral (anticlockwise)"), (gpointer) SPIRAL_ANTICLOCKWISE, NULL,
  336.  
  337.      NULL);
  338.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  339.                  _("Gradient:"), 1.0, 0.5,
  340.                  options->gradient_type_w, 1, TRUE);
  341.  
  342.   /*  the repeat option  */
  343.   options->repeat_w = gimp_option_menu_new2
  344.     (FALSE, gimp_menu_item_update,
  345.      &options->repeat, (gpointer) options->repeat_d,
  346.  
  347.      _("None"),            (gpointer) REPEAT_NONE, NULL,
  348.      _("Sawtooth Wave"),   (gpointer) REPEAT_SAWTOOTH, NULL,
  349.      _("Triangular Wave"), (gpointer) REPEAT_TRIANGULAR, NULL,
  350.  
  351.      NULL);
  352.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  353.                  _("Repeat:"), 1.0, 0.5,
  354.                  options->repeat_w, 1, TRUE);
  355.  
  356.   /*  show the table  */
  357.   gtk_widget_show (table);
  358.  
  359.   /*  frame for supersampling options  */
  360.   frame = gtk_frame_new (NULL);
  361.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  362.   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
  363.   gtk_widget_show (frame);
  364.  
  365.   /* vbox for the supersampling stuff */
  366.   vbox = gtk_vbox_new (FALSE, 0);
  367.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  368.   gtk_widget_show (vbox);
  369.  
  370.   /*  supersampling toggle  */
  371.   options->supersample_w =
  372.     gtk_check_button_new_with_label (_("Adaptive Supersampling"));
  373.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->supersample_w),
  374.                 options->supersample_d);
  375.   gtk_signal_connect (GTK_OBJECT (options->supersample_w), "toggled",
  376.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  377.               &options->supersample);
  378.   gtk_box_pack_start (GTK_BOX (vbox), options->supersample_w, FALSE, FALSE, 0);
  379.   gtk_widget_show (options->supersample_w);
  380.  
  381.   /*  table for supersampling options  */
  382.   table = gtk_table_new (2, 2, FALSE);
  383.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  384.   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4);
  385.   gtk_table_set_row_spacings (GTK_TABLE (table), 1);
  386.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  387.  
  388.   /*  automatically set the sensitive state of the table  */
  389.   gtk_widget_set_sensitive (table, options->supersample_d);
  390.   gtk_object_set_data (GTK_OBJECT (options->supersample_w), "set_sensitive",
  391.                table);
  392.  
  393.   /*  max depth scale  */
  394.   options->max_depth_w =
  395.     gtk_adjustment_new (options->max_depth_d, 1.0, 10.0, 1.0, 1.0, 1.0);
  396.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->max_depth_w));
  397.   gtk_scale_set_digits (GTK_SCALE (scale), 0);
  398.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  399.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  400.                  _("Max Depth:"), 1.0, 1.0,
  401.                  scale, 1, FALSE);
  402.   gtk_signal_connect (GTK_OBJECT(options->max_depth_w), "value_changed",
  403.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  404.               &options->max_depth);
  405.  
  406.   /*  threshold scale  */
  407.   options->threshold_w =
  408.     gtk_adjustment_new (options->threshold_d, 0.0, 4.0, 0.01, 0.01, 0.0);
  409.   scale = gtk_hscale_new (GTK_ADJUSTMENT (options->threshold_w));
  410.   gtk_scale_set_digits (GTK_SCALE (scale), 2);
  411.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  412.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  413.                  _("Threshold:"), 1.0, 1.0,
  414.                  scale, 1, FALSE);
  415.   gtk_signal_connect (GTK_OBJECT(options->threshold_w), "value_changed",
  416.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  417.               &options->threshold);
  418.  
  419.   /*  show the table  */
  420.   gtk_widget_show (table);
  421.  
  422.   return options;
  423. }
  424.  
  425.  
  426. static void
  427. blend_button_press (Tool           *tool,
  428.             GdkEventButton *bevent,
  429.             gpointer        gdisp_ptr)
  430. {
  431.   GDisplay * gdisp;
  432.   BlendTool * blend_tool;
  433.  
  434.   gdisp = (GDisplay *) gdisp_ptr;
  435.   blend_tool = (BlendTool *) tool->private;
  436.  
  437.   switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
  438.     {
  439.     case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
  440.       g_message (_("Blend: Invalid for indexed images."));
  441.       return;
  442.  
  443.       break;
  444.     default:
  445.       break;
  446.     }
  447.  
  448.   /*  Keep the coordinates of the target  */
  449.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
  450.                    &blend_tool->startx, &blend_tool->starty, 
  451.                                FALSE, TRUE);
  452.  
  453.   blend_tool->endx = blend_tool->startx;
  454.   blend_tool->endy = blend_tool->starty;
  455.  
  456.   /*  Make the tool active and set the gdisplay which owns it  */
  457.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  458.             GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
  459.             NULL, NULL, bevent->time);
  460.  
  461.   tool->gdisp_ptr = gdisp_ptr;
  462.   tool->state = ACTIVE;
  463.  
  464.   /* initialize the statusbar display */
  465.   blend_tool->context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "blend");
  466.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id, _("Blend: 0, 0"));
  467.  
  468.   /*  Start drawing the blend tool  */
  469.   draw_core_start (blend_tool->core, gdisp->canvas->window, tool);
  470. }
  471.  
  472. static void
  473. blend_button_release (Tool           *tool,
  474.               GdkEventButton *bevent,
  475.               gpointer        gdisp_ptr)
  476. {
  477.   GDisplay * gdisp;
  478.   GImage * gimage;
  479.   BlendTool * blend_tool;
  480. #ifdef BLEND_UI_CALLS_VIA_PDB
  481.   Argument *return_vals;
  482.   int nreturn_vals;
  483. #else
  484.   gimp_progress *progress;
  485. #endif
  486.  
  487.   gdisp = (GDisplay *) gdisp_ptr;
  488.   gimage = gdisp->gimage;
  489.   blend_tool = (BlendTool *) tool->private;
  490.  
  491.   gdk_pointer_ungrab (bevent->time);
  492.   gdk_flush ();
  493.  
  494.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id);
  495.  
  496.   draw_core_stop (blend_tool->core, tool);
  497.   tool->state = INACTIVE;
  498.  
  499.   /*  if the 3rd button isn't pressed, fill the selected region  */
  500.   if (! (bevent->state & GDK_BUTTON3_MASK) &&
  501.       ((blend_tool->startx != blend_tool->endx) ||
  502.        (blend_tool->starty != blend_tool->endy)))
  503.     {
  504.       /* we can't do callbacks easily with the PDB, so this UI/backend
  505.        * separation (though good) is ignored for the moment */
  506. #ifdef BLEND_UI_CALLS_VIA_PDB
  507.       return_vals = 
  508.     procedural_db_run_proc ("gimp_blend",
  509.                 &nreturn_vals,
  510.                 PDB_DRAWABLE, drawable_ID (gimage_active_drawable (gimage)),
  511.                 PDB_INT32, (gint32) blend_options->blend_mode,
  512.                 PDB_INT32, (gint32) PAINT_OPTIONS_GET_PAINT_MODE (blend_options),
  513.                 PDB_INT32, (gint32) blend_options->gradient_type,
  514.                 PDB_FLOAT, (gdouble) PAINT_OPTIONS_GET_OPACITY (blend_options) * 100,
  515.                 PDB_FLOAT, (gdouble) blend_options->offset,
  516.                 PDB_INT32, (gint32) blend_options->repeat,
  517.                 PDB_INT32, (gint32) blend_options->supersample,
  518.                 PDB_INT32, (gint32) blend_options->max_depth,
  519.                 PDB_FLOAT, (gdouble) blend_options->threshold,
  520.                 PDB_FLOAT, (gdouble) blend_tool->startx,
  521.                 PDB_FLOAT, (gdouble) blend_tool->starty,
  522.                 PDB_FLOAT, (gdouble) blend_tool->endx,
  523.                 PDB_FLOAT, (gdouble) blend_tool->endy,
  524.                 PDB_END);
  525.  
  526.       if (return_vals && return_vals[0].value.pdb_int == PDB_SUCCESS)
  527.     gdisplays_flush ();
  528.       else
  529.     g_message (_("Blend operation failed."));
  530.  
  531.       procedural_db_destroy_args (return_vals, nreturn_vals);
  532.  
  533. #else /* ! BLEND_UI_CALLS_VIA_PDB */
  534.  
  535.       progress = progress_start (gdisp, _("Blending..."), FALSE, NULL, NULL);
  536.  
  537.       blend (gimage,
  538.          gimage_active_drawable (gimage),
  539.          blend_options->blend_mode,
  540.          gimp_context_get_paint_mode (NULL),
  541.          blend_options->gradient_type,
  542.          gimp_context_get_opacity (NULL) * 100,
  543.          blend_options->offset,
  544.          blend_options->repeat,
  545.          blend_options->supersample,
  546.          blend_options->max_depth,
  547.          blend_options->threshold,
  548.          blend_tool->startx,
  549.          blend_tool->starty,
  550.          blend_tool->endx,
  551.          blend_tool->endy,
  552.          progress ? progress_update_and_flush : (progress_func_t)NULL, 
  553.          progress);
  554.  
  555.       if (progress)
  556.     progress_end (progress);
  557.  
  558.       gdisplays_flush ();
  559. #endif /* ! BLEND_UI_CALLS_VIA_PDB */
  560.     }
  561. }
  562.  
  563. static void
  564. blend_motion (Tool           *tool,
  565.           GdkEventMotion *mevent,
  566.           gpointer        gdisp_ptr)
  567. {
  568.   GDisplay * gdisp;
  569.   BlendTool * blend_tool;
  570.   gchar vector[STATUSBAR_SIZE];
  571.  
  572.   gdisp = (GDisplay *) gdisp_ptr;
  573.   blend_tool = (BlendTool *) tool->private;
  574.  
  575.   /*  undraw the current tool  */
  576.   draw_core_pause (blend_tool->core, tool);
  577.  
  578.   /*  Get the current coordinates  */
  579.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y,
  580.                    &blend_tool->endx, &blend_tool->endy, 
  581.                                FALSE, TRUE);
  582.  
  583.  
  584.   /* Restrict to multiples of 15 degrees if ctrl is pressed */
  585.   if (mevent->state & GDK_CONTROL_MASK)
  586.     {
  587.       int tangens2[6] = {  34, 106, 196, 334, 618, 1944 };
  588.       int cosinus[7]  = { 256, 247, 222, 181, 128, 66, 0 };
  589.       int dx, dy, i, radius, frac;
  590.  
  591.       dx = blend_tool->endx - blend_tool->startx;
  592.       dy = blend_tool->endy - blend_tool->starty;
  593.  
  594.       if (dy)
  595.     {
  596.       radius = sqrt (SQR (dx) + SQR (dy));
  597.       frac = abs ((dx << 8) / dy);
  598.       for (i = 0; i < 6; i++)
  599.         {
  600.           if (frac < tangens2[i])
  601.         break;  
  602.         }
  603.       dx = dx > 0 ? (cosinus[6-i] * radius) >> 8 : - ((cosinus[6-i] * radius) >> 8);
  604.       dy = dy > 0 ? (cosinus[i] * radius) >> 8 : - ((cosinus[i] * radius) >> 8);
  605.     }
  606.       blend_tool->endx = blend_tool->startx + dx;
  607.       blend_tool->endy = blend_tool->starty + dy;
  608.     }
  609.  
  610.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id);
  611.   if (gdisp->dot_for_dot)
  612.     {
  613.       g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str,
  614.           _("Blend: "),
  615.           blend_tool->endx - blend_tool->startx,
  616.           ", ",
  617.           blend_tool->endy - blend_tool->starty);
  618.     }
  619.   else /* show real world units */
  620.     {
  621.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  622.  
  623.       g_snprintf (vector, sizeof (vector), gdisp->cursor_format_str,
  624.           _("Blend: "),
  625.           blend_tool->endx - blend_tool->startx * unit_factor /
  626.           gdisp->gimage->xresolution,
  627.           ", ",
  628.           blend_tool->endy - blend_tool->starty * unit_factor /
  629.           gdisp->gimage->yresolution);
  630.     }
  631.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), blend_tool->context_id,
  632.               vector);
  633.  
  634.   /*  redraw the current tool  */
  635.   draw_core_resume (blend_tool->core, tool);
  636. }
  637.  
  638. static void
  639. blend_cursor_update (Tool           *tool,
  640.              GdkEventMotion *mevent,
  641.              gpointer        gdisp_ptr)
  642. {
  643.   GDisplay * gdisp;
  644.  
  645.   gdisp = (GDisplay *) gdisp_ptr;
  646.  
  647.   switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
  648.     {
  649.     case INDEXED_GIMAGE:
  650.     case INDEXEDA_GIMAGE:
  651.       gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
  652.                     BLEND,
  653.                     CURSOR_MODIFIER_NONE,
  654.                     FALSE);
  655.       break;
  656.     default:
  657.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  658.                     BLEND,
  659.                     CURSOR_MODIFIER_NONE,
  660.                     FALSE);
  661.       break;
  662.     }
  663. }
  664.  
  665. static void
  666. blend_draw (Tool *tool)
  667. {
  668.   GDisplay * gdisp;
  669.   BlendTool * blend_tool;
  670.   int tx1, ty1, tx2, ty2;
  671.  
  672.   gdisp = (GDisplay *) tool->gdisp_ptr;
  673.   blend_tool = (BlendTool *) tool->private;
  674.  
  675.   gdisplay_transform_coords (gdisp, blend_tool->startx, blend_tool->starty,
  676.                  &tx1, &ty1, TRUE);
  677.   gdisplay_transform_coords (gdisp, blend_tool->endx, blend_tool->endy,
  678.                  &tx2, &ty2, TRUE);
  679.  
  680.   /*  Draw start target  */
  681.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  682.          tx1 - (TARGET_WIDTH >> 1), ty1,
  683.          tx1 + (TARGET_WIDTH >> 1), ty1);
  684.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  685.          tx1, ty1 - (TARGET_HEIGHT >> 1),
  686.          tx1, ty1 + (TARGET_HEIGHT >> 1));
  687.  
  688.   /*  Draw end target  */
  689.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  690.          tx2 - (TARGET_WIDTH >> 1), ty2,
  691.          tx2 + (TARGET_WIDTH >> 1), ty2);
  692.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  693.          tx2, ty2 - (TARGET_HEIGHT >> 1),
  694.          tx2, ty2 + (TARGET_HEIGHT >> 1));
  695.  
  696.   /*  Draw the line between the start and end coords  */
  697.   gdk_draw_line (blend_tool->core->win, blend_tool->core->gc,
  698.          tx1, ty1, tx2, ty2);
  699. }
  700.  
  701. static void
  702. blend_control (Tool       *tool,
  703.            ToolAction  action,
  704.            gpointer    gdisp_ptr)
  705. {
  706.   BlendTool * blend_tool;
  707.  
  708.   blend_tool = (BlendTool *) tool->private;
  709.  
  710.   switch (action)
  711.     {
  712.     case PAUSE:
  713.       draw_core_pause (blend_tool->core, tool);
  714.       break;
  715.  
  716.     case RESUME:
  717.       draw_core_resume (blend_tool->core, tool);
  718.       break;
  719.  
  720.     case HALT:
  721.       draw_core_stop (blend_tool->core, tool);
  722.       break;
  723.  
  724.     default:
  725.       break;
  726.     }
  727. }
  728.  
  729.  
  730. static void
  731. blend_options_drop_gradient (GtkWidget  *widget,
  732.                  gradient_t *gradient,
  733.                  gpointer    data)
  734. {
  735.   gimp_context_set_gradient (gimp_context_get_user (), gradient);
  736.   gtk_option_menu_set_history (GTK_OPTION_MENU (blend_options->blend_mode_w), 
  737.                    CUSTOM_MODE);
  738.   blend_options->blend_mode = CUSTOM_MODE;
  739. }
  740.  
  741. static void
  742. blend_options_drop_tool (GtkWidget *widget,
  743.              ToolType   tool,
  744.              gpointer   data)
  745. {
  746.   gimp_context_set_tool (gimp_context_get_user (), tool);
  747. }
  748.  
  749.  
  750. /*****/
  751.  
  752. /*  The actual blending procedure  */
  753. void
  754. blend (GImage          *gimage,
  755.        GimpDrawable    *drawable,
  756.        BlendMode        blend_mode,
  757.        int              paint_mode,
  758.        GradientType     gradient_type,
  759.        double           opacity,
  760.        double           offset,
  761.        RepeatMode       repeat,
  762.        int              supersample,
  763.        int              max_depth,
  764.        double           threshold,
  765.        double           startx,
  766.        double           starty,
  767.        double           endx,
  768.        double           endy,
  769.        progress_func_t  progress_callback,
  770.        void            *progress_data)
  771. {
  772.   TileManager *buf_tiles;
  773.   PixelRegion bufPR;
  774.   int has_alpha;
  775.   int has_selection;
  776.   int bytes;
  777.   int x1, y1, x2, y2;
  778.  
  779.   gimp_add_busy_cursors();
  780.  
  781.   has_selection = drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  782.  
  783.   has_alpha = drawable_has_alpha (drawable);
  784.   bytes = drawable_bytes (drawable);
  785.  
  786.   /*  Always create an alpha temp buf (for generality) */
  787.   if (! has_alpha)
  788.     {
  789.       has_alpha = TRUE;
  790.       bytes += 1;
  791.     }
  792.  
  793.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
  794.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  795.  
  796.   gradient_fill_region (gimage, drawable,
  797.               &bufPR, (x2 - x1), (y2 - y1),
  798.             blend_mode, gradient_type, offset, repeat,
  799.             supersample, max_depth, threshold,
  800.             (startx - x1), (starty - y1),
  801.             (endx - x1), (endy - y1),
  802.             progress_callback, progress_data);
  803.  
  804.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  805.   gimage_apply_image (gimage, drawable, &bufPR, TRUE,
  806.               (opacity * 255) / 100, paint_mode, NULL, x1, y1);
  807.  
  808.   /*  update the image  */
  809.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  810.  
  811.   /*  free the temporary buffer  */
  812.   tile_manager_destroy (buf_tiles);
  813.  
  814.   gimp_remove_busy_cursors(NULL);
  815. }
  816.  
  817.  
  818. static double
  819. gradient_calc_conical_sym_factor (double  dist,
  820.                   double *axis,
  821.                   double  offset,
  822.                   double  x,
  823.                   double  y)
  824. {
  825.   double vec[2];
  826.   double r;
  827.   double rat;
  828.  
  829.   if (dist == 0.0)
  830.     rat = 0.0;
  831.   else
  832.     if ((x != 0) || (y != 0))
  833.       {
  834.     /* Calculate offset from the start in pixels */
  835.  
  836.     r = sqrt(x * x + y * y);
  837.  
  838.     vec[0] = x / r;
  839.     vec[1] = y / r;
  840.  
  841.     rat = axis[0] * vec[0] + axis[1] * vec[1]; /* Dot product */
  842.  
  843.     if (rat > 1.0)
  844.       rat = 1.0;
  845.     else if (rat < -1.0)
  846.       rat = -1.0;
  847.  
  848.     /* This cool idea is courtesy Josh MacDonald,
  849.      * Ali Rahimi --- two more XCF losers.  */
  850.  
  851.     rat = acos(rat) / G_PI;
  852.     rat = pow(rat, (offset / 10) + 1);
  853.  
  854.     rat = CLAMP(rat, 0.0, 1.0);
  855.       }
  856.     else
  857.       rat = 0.5;
  858.  
  859.   return rat;
  860. } /* gradient_calc_conical_sym_factor */
  861.  
  862.  
  863. /*****/
  864.  
  865. static double
  866. gradient_calc_conical_asym_factor (double  dist,
  867.                    double *axis,
  868.                    double  offset,
  869.                    double  x,
  870.                    double  y)
  871. {
  872.   double ang0, ang1;
  873.   double ang;
  874.   double rat;
  875.  
  876.   if (dist == 0.0)
  877.     rat = 0.0;
  878.   else
  879.     {
  880.       if ((x != 0) || (y != 0))
  881.     {
  882.       ang0 = atan2(axis[0], axis[1]) + G_PI;
  883.       ang1 = atan2(x, y) + G_PI;
  884.  
  885.       ang = ang1 - ang0;
  886.  
  887.       if (ang < 0.0)
  888.         ang += (2.0 * G_PI);
  889.  
  890.       rat = ang / (2.0 * G_PI);
  891.       rat = pow(rat, (offset / 10) + 1);
  892.  
  893.       rat = CLAMP(rat, 0.0, 1.0);
  894.     }
  895.       else
  896.     rat = 0.5; /* We are on middle point */
  897.     } /* else */
  898.  
  899.   return rat;
  900. } /* gradient_calc_conical_asym_factor */
  901.  
  902.  
  903. /*****/
  904.  
  905. static double
  906. gradient_calc_square_factor (double dist,
  907.                  double offset,
  908.                  double x,
  909.                  double y)
  910. {
  911.   double r;
  912.   double rat;
  913.  
  914.   if (dist == 0.0)
  915.     rat = 0.0;
  916.   else
  917.     {
  918.       /* Calculate offset from start as a value in [0, 1] */
  919.  
  920.       offset = offset / 100.0;
  921.  
  922.       r   = MAX (abs (x), abs (y));
  923.       rat = r / dist;
  924.  
  925.       if (rat < offset)
  926.     rat = 0.0;
  927.       else if (offset == 1)
  928.         rat = (rat>=1) ? 1 : 0;
  929.       else
  930.     rat = (rat - offset) / (1.0 - offset);
  931.     } /* else */
  932.  
  933.   return rat;
  934. } /* gradient_calc_square_factor */
  935.  
  936.  
  937. /*****/
  938.  
  939. static double
  940. gradient_calc_radial_factor (double dist,
  941.                  double offset,
  942.                  double x,
  943.                  double y)
  944. {
  945.   double r;
  946.   double rat;
  947.  
  948.   if (dist == 0.0)
  949.     rat = 0.0;
  950.   else
  951.     {
  952.       /* Calculate radial offset from start as a value in [0, 1] */
  953.  
  954.       offset = offset / 100.0;
  955.  
  956.       r   = sqrt(SQR(x) + SQR(y));
  957.       rat = r / dist;
  958.  
  959.       if (rat < offset)
  960.     rat = 0.0;
  961.       else if (offset == 1)
  962.         rat = (rat>=1) ? 1 : 0;
  963.       else
  964.     rat = (rat - offset) / (1.0 - offset);
  965.     } /* else */
  966.  
  967.   return rat;
  968. } /* gradient_calc_radial_factor */
  969.  
  970.  
  971. /*****/
  972.  
  973. static double
  974. gradient_calc_linear_factor (double  dist,
  975.                  double *vec,
  976.                  double  offset,
  977.                  double  x,
  978.                  double  y)
  979. {
  980.   double r;
  981.   double rat;
  982.  
  983.   if (dist == 0.0)
  984.     rat = 0.0;
  985.   else
  986.     {
  987.       offset = offset / 100.0;
  988.  
  989.       r   = vec[0] * x + vec[1] * y;
  990.       rat = r / dist;
  991.  
  992.       if (rat < offset)
  993.     rat = 0.0;
  994.       else if (offset == 1)
  995.         rat = (rat>=1) ? 1 : 0;
  996.       else
  997.     rat = (rat - offset) / (1.0 - offset);
  998.     } /* else */
  999.  
  1000.   return rat;
  1001. } /* gradient_calc_linear_factor */
  1002.  
  1003.  
  1004. /*****/
  1005.  
  1006. static double
  1007. gradient_calc_bilinear_factor (double  dist,
  1008.                    double *vec,
  1009.                    double  offset,
  1010.                    double  x,
  1011.                    double  y)
  1012. {
  1013.   double r;
  1014.   double rat;
  1015.  
  1016.   if (dist == 0.0)
  1017.     rat = 0.0;
  1018.   else
  1019.     {
  1020.       /* Calculate linear offset from the start line outward */
  1021.  
  1022.       offset = offset / 100.0;
  1023.  
  1024.       r   = vec[0] * x + vec[1] * y;
  1025.       rat = r / dist;
  1026.  
  1027.       if (fabs(rat) < offset)
  1028.     rat = 0.0;
  1029.       else if (offset == 1)
  1030.         rat = (rat>=1) ? 1 : 0;
  1031.       else
  1032.     rat = (fabs(rat) - offset) / (1.0 - offset);
  1033.     } /* else */
  1034.  
  1035.   return rat;
  1036. } /* gradient_calc_bilinear_factor */
  1037.  
  1038. static double
  1039. gradient_calc_spiral_factor (double  dist,
  1040.                  double *axis,
  1041.                  double  offset,
  1042.                  double  x,
  1043.                  double  y,
  1044.                  gint    cwise)
  1045. {
  1046.   double ang0, ang1;
  1047.   double ang, r;
  1048.   double rat;
  1049.  
  1050.   if (dist == 0.0)
  1051.     rat = 0.0;
  1052.   else
  1053.     {
  1054.       if (x != 0.0 || y != 0.0)
  1055.     {
  1056.       ang0 = atan2 (axis[0], axis[1]) + G_PI;
  1057.       ang1 = atan2 (x, y) + G_PI;
  1058.       if(!cwise)
  1059.         ang = ang0 - ang1;
  1060.       else
  1061.         ang = ang1 - ang0;
  1062.  
  1063.       if (ang < 0.0)
  1064.         ang += (2.0 * G_PI);
  1065.  
  1066.       r = sqrt (x * x + y * y) / dist;
  1067.       rat = ang / (2.0 * G_PI) + r + offset;
  1068.       rat = fmod (rat, 1.0);
  1069.     }
  1070.       else
  1071.     rat = 0.5 ; /* We are on the middle point */
  1072.     }
  1073.  
  1074.   return rat;
  1075. }
  1076.  
  1077. static double
  1078. gradient_calc_shapeburst_angular_factor (double x,
  1079.                      double y)
  1080. {
  1081.   int ix, iy;
  1082.   Tile *tile;
  1083.   float value;
  1084.  
  1085.   ix = (int) CLAMP (x, 0, distR.w);
  1086.   iy = (int) CLAMP (y, 0, distR.h);
  1087.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1088.   value = 1.0 - *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1089.   tile_release (tile, FALSE);
  1090.  
  1091.   return value;
  1092. }
  1093.  
  1094.  
  1095. static double
  1096. gradient_calc_shapeburst_spherical_factor (double x,
  1097.                        double y)
  1098. {
  1099.   int ix, iy;
  1100.   Tile *tile;
  1101.   float value;
  1102.  
  1103.   ix = (int) CLAMP (x, 0, distR.w);
  1104.   iy = (int) CLAMP (y, 0, distR.h);
  1105.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1106.   value = *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1107.   value = 1.0 - sin (0.5 * G_PI * value);
  1108.   tile_release (tile, FALSE);
  1109.  
  1110.   return value;
  1111. }
  1112.  
  1113.  
  1114. static double
  1115. gradient_calc_shapeburst_dimpled_factor (double x,
  1116.                      double y)
  1117. {
  1118.   int ix, iy;
  1119.   Tile *tile;
  1120.   float value;
  1121.  
  1122.   ix = (int) CLAMP (x, 0, distR.w);
  1123.   iy = (int) CLAMP (y, 0, distR.h);
  1124.   tile = tile_manager_get_tile (distR.tiles, ix, iy, TRUE, FALSE);
  1125.   value = *((float *) tile_data_pointer (tile, ix % TILE_WIDTH, iy % TILE_HEIGHT));
  1126.   value = cos (0.5 * G_PI * value);
  1127.   tile_release (tile, FALSE);
  1128.  
  1129.   return value;
  1130. }
  1131.  
  1132. static double
  1133. gradient_repeat_none (double val)
  1134. {
  1135.   return CLAMP(val, 0.0, 1.0);
  1136. }
  1137.  
  1138. static double
  1139. gradient_repeat_sawtooth (double val)
  1140. {
  1141.   if (val >= 0.0)
  1142.     return fmod(val, 1.0);
  1143.   else
  1144.     return 1.0 - fmod(-val, 1.0);
  1145. }
  1146.  
  1147. static double
  1148. gradient_repeat_triangular (double val)
  1149. {
  1150.   int ival;
  1151.  
  1152.   if (val < 0.0)
  1153.     val = -val;
  1154.  
  1155.   ival = (int) val;
  1156.  
  1157.   if (ival & 1)
  1158.     return 1.0 - fmod(val, 1.0);
  1159.   else
  1160.     return fmod(val, 1.0);
  1161. }
  1162.  
  1163. /*****/
  1164. static void
  1165. gradient_precalc_shapeburst (GImage       *gimage,
  1166.                  GimpDrawable *drawable,
  1167.                  PixelRegion  *PR,
  1168.                  double        dist)
  1169. {
  1170.   Channel *mask;
  1171.   PixelRegion tempR;
  1172.   float max_iteration;
  1173.   float *distp;
  1174.   int size;
  1175.   void * pr;
  1176.   unsigned char white[1] = { OPAQUE_OPACITY };
  1177.  
  1178.   /*  allocate the distance map  */
  1179.   if (distR.tiles)
  1180.     tile_manager_destroy (distR.tiles);
  1181.   distR.tiles = tile_manager_new (PR->w, PR->h, sizeof (float));
  1182.  
  1183.   /*  allocate the selection mask copy  */
  1184.   tempR.tiles = tile_manager_new (PR->w, PR->h, 1);
  1185.   pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1186.  
  1187.   /*  If the gimage mask is not empty, use it as the shape burst source  */
  1188.   if (! gimage_mask_is_empty (gimage))
  1189.     {
  1190.       PixelRegion maskR;
  1191.       int x1, y1, x2, y2;
  1192.       int offx, offy;
  1193.  
  1194.       drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  1195.       drawable_offsets (drawable, &offx, &offy);
  1196.  
  1197.       /*  the selection mask  */
  1198.       mask = gimage_get_mask (gimage);
  1199.       pixel_region_init (&maskR, drawable_data (GIMP_DRAWABLE(mask)), 
  1200.              x1 + offx, y1 + offy, (x2 - x1), (y2 - y1), FALSE);
  1201.  
  1202.       /*  copy the mask to the temp mask  */
  1203.       copy_region (&maskR, &tempR);
  1204.     }
  1205.   /*  otherwise...  */
  1206.   else
  1207.     {
  1208.       /*  If the intended drawable has an alpha channel, use that  */
  1209.       if (drawable_has_alpha (drawable))
  1210.     {
  1211.       PixelRegion drawableR;
  1212.  
  1213.       pixel_region_init (&drawableR, drawable_data (drawable), PR->x, PR->y, PR->w, PR->h, FALSE);
  1214.  
  1215.       extract_alpha_region (&drawableR, NULL, &tempR);
  1216.     }
  1217.       /*  Otherwise, just fill the shapeburst to white  */
  1218.       else
  1219.     color_region (&tempR, white);
  1220.     }
  1221.  
  1222.   pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1223.   pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1224.   max_iteration = shapeburst_region (&tempR, &distR);
  1225.  
  1226.   /*  normalize the shapeburst with the max iteration  */
  1227.   if (max_iteration > 0)
  1228.     {
  1229.       pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
  1230.  
  1231.       for (pr = pixel_regions_register (1, &distR); pr != NULL; pr = pixel_regions_process (pr))
  1232.     {
  1233.       distp = (float *) distR.data;
  1234.       size = distR.w * distR.h;
  1235.  
  1236.       while (size--)
  1237.         *distp++ /= max_iteration;
  1238.     }
  1239.  
  1240.       pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, FALSE);
  1241.     }
  1242.  
  1243.   tile_manager_destroy (tempR.tiles);
  1244. }
  1245.  
  1246.  
  1247. static void
  1248. gradient_render_pixel (double   x, 
  1249.                double   y, 
  1250.                color_t *color, 
  1251.                void    *render_data)
  1252. {
  1253.   RenderBlendData *rbd;
  1254.   double           factor;
  1255.  
  1256.   rbd = render_data;
  1257.  
  1258.   /* Calculate blending factor */
  1259.  
  1260.   switch (rbd->gradient_type)
  1261.     {
  1262.     case RADIAL:
  1263.       factor = gradient_calc_radial_factor (rbd->dist, rbd->offset,
  1264.                         x - rbd->sx, y - rbd->sy);
  1265.       break;
  1266.  
  1267.     case CONICAL_SYMMETRIC:
  1268.       factor = gradient_calc_conical_sym_factor (rbd->dist, rbd->vec, rbd->offset,
  1269.                          x - rbd->sx, y - rbd->sy);
  1270.       break;
  1271.  
  1272.     case CONICAL_ASYMMETRIC:
  1273.       factor = gradient_calc_conical_asym_factor (rbd->dist, rbd->vec, rbd->offset,
  1274.                           x - rbd->sx, y - rbd->sy);
  1275.       break;
  1276.  
  1277.     case SQUARE:
  1278.       factor = gradient_calc_square_factor (rbd->dist, rbd->offset,
  1279.                         x - rbd->sx, y - rbd->sy);
  1280.       break;
  1281.  
  1282.     case LINEAR:
  1283.       factor = gradient_calc_linear_factor (rbd->dist, rbd->vec, rbd->offset,
  1284.                         x - rbd->sx, y - rbd->sy);
  1285.       break;
  1286.  
  1287.     case BILINEAR:
  1288.       factor = gradient_calc_bilinear_factor (rbd->dist, rbd->vec, rbd->offset,
  1289.                           x - rbd->sx, y - rbd->sy);
  1290.       break;
  1291.  
  1292.     case SHAPEBURST_ANGULAR:
  1293.       factor = gradient_calc_shapeburst_angular_factor (x, y);
  1294.       break;
  1295.  
  1296.     case SHAPEBURST_SPHERICAL:
  1297.       factor = gradient_calc_shapeburst_spherical_factor (x, y);
  1298.       break;
  1299.  
  1300.     case SHAPEBURST_DIMPLED:
  1301.       factor = gradient_calc_shapeburst_dimpled_factor (x, y);
  1302.       break;
  1303.  
  1304.     case SPIRAL_CLOCKWISE:
  1305.       factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset,
  1306.                         x - rbd->sx, y - rbd->sy,TRUE);
  1307.       break;
  1308.  
  1309.     case SPIRAL_ANTICLOCKWISE:
  1310.       factor = gradient_calc_spiral_factor (rbd->dist, rbd->vec, rbd->offset,
  1311.                         x - rbd->sx, y - rbd->sy,FALSE);
  1312.       break;
  1313.  
  1314.     default:
  1315.       gimp_fatal_error ("gradient_render_pixel(): Unknown gradient type %d",
  1316.             (int) rbd->gradient_type);
  1317.       return;
  1318.     }
  1319.  
  1320.   /* Adjust for repeat */
  1321.  
  1322.   factor = (*rbd->repeat_func)(factor);
  1323.  
  1324.   /* Blend the colors */
  1325.  
  1326.   if (rbd->blend_mode == CUSTOM_MODE)
  1327.     gradient_get_color_at (gimp_context_get_gradient (NULL),
  1328.                factor, &color->r, &color->g, &color->b, &color->a);
  1329.   else
  1330.     {
  1331.       /* Blend values */
  1332.  
  1333.       color->r = rbd->fg.r + (rbd->bg.r - rbd->fg.r) * factor;
  1334.       color->g = rbd->fg.g + (rbd->bg.g - rbd->fg.g) * factor;
  1335.       color->b = rbd->fg.b + (rbd->bg.b - rbd->fg.b) * factor;
  1336.       color->a = rbd->fg.a + (rbd->bg.a - rbd->fg.a) * factor;
  1337.  
  1338.       if (rbd->blend_mode == FG_BG_HSV_MODE)
  1339.     gimp_hsv_to_rgb_double (&color->r, &color->g, &color->b);
  1340.     }
  1341. }
  1342.  
  1343. static void
  1344. gradient_put_pixel (int      x, 
  1345.             int      y, 
  1346.             color_t  color, 
  1347.             void    *put_pixel_data)
  1348. {
  1349.   PutPixelData  *ppd;
  1350.   unsigned char *data;
  1351.  
  1352.   ppd = put_pixel_data;
  1353.  
  1354.   /* Paint */
  1355.  
  1356.   data = ppd->row_data + ppd->bytes * x;
  1357.  
  1358.   if (ppd->bytes >= 3)
  1359.     {
  1360.       *data++ = color.r * 255.0;
  1361.       *data++ = color.g * 255.0;
  1362.       *data++ = color.b * 255.0;
  1363.       *data++ = color.a * 255.0;
  1364.     }
  1365.   else
  1366.     {
  1367.       /* Convert to grayscale */
  1368.  
  1369.       *data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
  1370.       *data++ = color.a * 255.0;
  1371.     }
  1372.  
  1373.   /* Paint whole row if we are on the rightmost pixel */
  1374.  
  1375.   if (x == (ppd->width - 1))
  1376.     pixel_region_set_row(ppd->PR, 0, y, ppd->width, ppd->row_data);
  1377. }
  1378.  
  1379. static void
  1380. gradient_fill_region (GImage          *gimage,
  1381.               GimpDrawable    *drawable,
  1382.               PixelRegion     *PR,
  1383.               int              width,
  1384.               int              height,
  1385.               BlendMode        blend_mode,
  1386.               GradientType     gradient_type,
  1387.               double           offset,
  1388.               RepeatMode       repeat,
  1389.               int              supersample,
  1390.               int              max_depth,
  1391.               double           threshold,
  1392.               double           sx,
  1393.               double           sy,
  1394.               double           ex,
  1395.               double           ey,
  1396.               progress_func_t  progress_callback,
  1397.               void            *progress_data)
  1398. {
  1399.   RenderBlendData  rbd;
  1400.   PutPixelData     ppd;
  1401.   unsigned char    r, g, b;
  1402.   int              x, y;
  1403.   int              endx, endy;
  1404.   void            *pr;
  1405.   unsigned char   *data;
  1406.   color_t          color;
  1407.  
  1408.   /* Get foreground and background colors, normalized */
  1409.  
  1410.   gimp_context_get_foreground (NULL, &r, &g, &b);
  1411.  
  1412.   rbd.fg.r = r / 255.0;
  1413.   rbd.fg.g = g / 255.0;
  1414.   rbd.fg.b = b / 255.0;
  1415.   rbd.fg.a = 1.0;  /* Foreground is always opaque */
  1416.  
  1417.   gimp_context_get_background (NULL, &r, &g, &b);
  1418.  
  1419.   rbd.bg.r = r / 255.0;
  1420.   rbd.bg.g = g / 255.0;
  1421.   rbd.bg.b = b / 255.0;
  1422.   rbd.bg.a = 1.0; /* opaque, for now */
  1423.  
  1424.   switch (blend_mode)
  1425.     {
  1426.     case FG_BG_RGB_MODE:
  1427.       break;
  1428.  
  1429.     case FG_BG_HSV_MODE:
  1430.       /* Convert to HSV */
  1431.  
  1432.       gimp_rgb_to_hsv_double(&rbd.fg.r, &rbd.fg.g, &rbd.fg.b);
  1433.       gimp_rgb_to_hsv_double(&rbd.bg.r, &rbd.bg.g, &rbd.bg.b);
  1434.  
  1435.       break;
  1436.  
  1437.     case FG_TRANS_MODE:
  1438.       /* Color does not change, just the opacity */
  1439.  
  1440.       rbd.bg   = rbd.fg;
  1441.       rbd.bg.a = 0.0; /* transparent */
  1442.  
  1443.       break;
  1444.  
  1445.     case CUSTOM_MODE:
  1446.       break;
  1447.  
  1448.     default:
  1449.       gimp_fatal_error("gradient_fill_region(): Unknown blend mode %d",
  1450.                (int) blend_mode);
  1451.       break;
  1452.     }
  1453.  
  1454.   /* Calculate type-specific parameters */
  1455.  
  1456.   switch (gradient_type)
  1457.     {
  1458.     case RADIAL:
  1459.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1460.       break;
  1461.  
  1462.     case SQUARE:
  1463.       rbd.dist = MAX (fabs (ex - sx), fabs (ey - sy));
  1464.       break;
  1465.  
  1466.     case CONICAL_SYMMETRIC:
  1467.     case CONICAL_ASYMMETRIC:
  1468.     case SPIRAL_CLOCKWISE:
  1469.     case SPIRAL_ANTICLOCKWISE:
  1470.     case LINEAR:
  1471.     case BILINEAR:
  1472.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1473.  
  1474.       if (rbd.dist > 0.0)
  1475.     {
  1476.       rbd.vec[0] = (ex - sx) / rbd.dist;
  1477.       rbd.vec[1] = (ey - sy) / rbd.dist;
  1478.     }
  1479.  
  1480.       break;
  1481.  
  1482.     case SHAPEBURST_ANGULAR:
  1483.     case SHAPEBURST_SPHERICAL:
  1484.     case SHAPEBURST_DIMPLED:
  1485.       rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
  1486.       gradient_precalc_shapeburst(gimage, drawable, PR, rbd.dist);
  1487.       break;
  1488.  
  1489.     default:
  1490.       gimp_fatal_error("gradient_fill_region(): Unknown gradient type %d",
  1491.                (int) gradient_type);
  1492.       break;
  1493.     }
  1494.  
  1495.   /* Set repeat function */
  1496.  
  1497.   switch (repeat)
  1498.     {
  1499.     case REPEAT_NONE:
  1500.       rbd.repeat_func = gradient_repeat_none;
  1501.       break;
  1502.  
  1503.     case REPEAT_SAWTOOTH:
  1504.       rbd.repeat_func = gradient_repeat_sawtooth;
  1505.       break;
  1506.  
  1507.     case REPEAT_TRIANGULAR:
  1508.       rbd.repeat_func = gradient_repeat_triangular;
  1509.       break;
  1510.  
  1511.     default:
  1512.       gimp_fatal_error("gradient_fill_region(): Unknown repeat mode %d",
  1513.                (int) repeat);
  1514.       break;
  1515.     }
  1516.  
  1517.   /* Initialize render data */
  1518.  
  1519.   rbd.offset        = offset;
  1520.   rbd.sx            = sx;
  1521.   rbd.sy            = sy;
  1522.   rbd.blend_mode    = blend_mode;
  1523.   rbd.gradient_type = gradient_type;
  1524.  
  1525.   /* Render the gradient! */
  1526.  
  1527.   if (supersample)
  1528.     {
  1529.       /* Initialize put pixel data */
  1530.  
  1531.       ppd.PR       = PR;
  1532.       ppd.row_data = g_malloc(width * PR->bytes);
  1533.       ppd.bytes    = PR->bytes;
  1534.       ppd.width    = width;
  1535.  
  1536.       /* Render! */
  1537.  
  1538.       adaptive_supersample_area(0, 0, (width - 1), (height - 1),
  1539.                 max_depth, threshold,
  1540.                 gradient_render_pixel, &rbd,
  1541.                 gradient_put_pixel, &ppd,
  1542.                 progress_callback, progress_data);
  1543.  
  1544.       /* Clean up */
  1545.  
  1546.       g_free(ppd.row_data);
  1547.     }
  1548.   else
  1549.     {
  1550.       int max_progress = PR->w * PR->h;
  1551.       int progress = 0;
  1552.  
  1553.       for (pr = pixel_regions_register(1, PR); pr != NULL; pr = pixel_regions_process(pr))
  1554.     {
  1555.       data = PR->data;
  1556.       endx = PR->x + PR->w;
  1557.       endy = PR->y + PR->h;
  1558.  
  1559.       for (y = PR->y; y < endy; y++)
  1560.         for (x = PR->x; x < endx; x++)
  1561.           {
  1562.         gradient_render_pixel(x, y, &color, &rbd);
  1563.  
  1564.         if (PR->bytes >= 3)
  1565.           {
  1566.             *data++ = color.r * 255.0;
  1567.             *data++ = color.g * 255.0;
  1568.             *data++ = color.b * 255.0;
  1569.             *data++ = color.a * 255.0;
  1570.           }
  1571.         else
  1572.           {
  1573.             /* Convert to grayscale */
  1574.  
  1575.             *data++ = 255.0 * INTENSITY (color.r, color.g, color.b);
  1576.             *data++ = color.a * 255.0;
  1577.           }
  1578.           }
  1579.  
  1580.       progress += PR->w * PR->h;
  1581.       if (progress_callback)
  1582.         (*progress_callback) (0, max_progress, progress, progress_data);
  1583.     }
  1584.     }
  1585. }
  1586.  
  1587. /****************************/
  1588. /*  Global blend functions  */
  1589. /****************************/
  1590.  
  1591. Tool *
  1592. tools_new_blend ()
  1593. {
  1594.   Tool * tool;
  1595.   BlendTool * private;
  1596.  
  1597.   /*  The tool options  */
  1598.   if (! blend_options)
  1599.     {
  1600.       blend_options = blend_options_new ();
  1601.       tools_register (BLEND, (ToolOptions *) blend_options);
  1602.     }
  1603.  
  1604.   tool = tools_new_tool (BLEND);
  1605.   private = g_new0 (BlendTool, 1);
  1606.  
  1607.   private->core = draw_core_new (blend_draw);
  1608.  
  1609.   tool->scroll_lock = TRUE;  /*  Disallow scrolling  */
  1610.  
  1611.   tool->private = (void *) private;
  1612.  
  1613.   tool->button_press_func   = blend_button_press;
  1614.   tool->button_release_func = blend_button_release;
  1615.   tool->motion_func         = blend_motion;
  1616.   tool->cursor_update_func  = blend_cursor_update;
  1617.   tool->control_func        = blend_control;
  1618.  
  1619.   return tool;
  1620. }
  1621.  
  1622. void
  1623. tools_free_blend (Tool *tool)
  1624. {
  1625.   BlendTool * blend_tool;
  1626.  
  1627.   blend_tool = (BlendTool *) tool->private;
  1628.  
  1629.   if (tool->state == ACTIVE)
  1630.     draw_core_stop (blend_tool->core, tool);
  1631.  
  1632.   draw_core_free (blend_tool->core);
  1633.  
  1634.   /*  free the distance map data if it exists  */
  1635.   if (distR.tiles)
  1636.     tile_manager_destroy (distR.tiles);
  1637.   distR.tiles = NULL;
  1638.  
  1639.   g_free (blend_tool);
  1640. }
  1641.